# 多任务异步协程
import requests
import time
from lxml import etree

import aiohttp
import asyncio

start_time = time.time()

# 用来存储视频链接、视频名称
video_msg = []

# 01. 指定 url
url = 'https://pearvideo.com/category_1'

# 02. 发起请求，使用 get 方法发起 get 请求，该方法回返回一个响应对象。参数 url 表示请求相应的 url。
headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"
}


# 03. 获取响应数据：通过调用响应对象的 text 属性，返回响应对象中存储的字符串形式的响应数据（页面源码数据）
def get_video_mag():
    print('正在爬取：', url)
    resp = requests.get(url, headers=headers)
    resp.encoding = 'utf-8'
    resp.close()
    if resp.status_code == 200:
        tree = etree.HTML(resp.content)
        # 获取视频所在的标签
        li_list = tree.xpath('//ul[@id="listvideoListUl"]/li')

        for li in li_list:
            detail_url = 'https://pearvideo.com/' + li.xpath('./div/a/@href')[0]
            name = li.xpath('./div/a/div[2]/text()')[0]
            print(name, ': ', detail_url)

            # 1. 拿到 contId
            # 'https://pearvideo.com/video_1679537'
            contId = detail_url.split('_')[1]
            print('contId: ', contId)

            # 2. 拿到 videoStatus 返回的 json -> srcURL
            videoStatus = f'https://pearvideo.com/videoStatus.jsp?contId={contId}&mrd=0.7631135027610461'
            heads = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
                # 防盗链：溯源，本次请求的上一个请求是谁
                'Referer': f'https://pearvideo.com/video_{contId}'
            }

            resp = requests.get(videoStatus, headers=heads)
            resp.close()

            # print('返回json: ', resp.text)

            # 3. srcURL 里面的内容进行修正
            dic = resp.json()
            srcURL = dic['videoInfo']['videos']['srcUrl']
            systemTime = dic['systemTime']
            srcURL = srcURL.replace(systemTime, 'cont-' + contId)

            print('mp4-URL: ', srcURL)

            video_dic = {
                'name': name,
                'url': srcURL
            }
            video_msg.append(video_dic)


# 4. 下载视频
async def download_video(video_name, video_url):
    # 在异步协程中，如果出现了同步模块儿相关的代码，那么就无法实现异步
    # 在 asyncio 中遇到阻塞操作必须进行手动挂起
    async with aiohttp.ClientSession() as session:
        async with await session.get(video_url) as resp:  # 一般 await 挂起操作，放在协程对象前面
            with open(f'./梨视频/{video_name}.mp4', mode='wb') as file:
                print(video_name, '.mp4，下载中······')
                file.write(await resp.content.read())  # read() 返回二进制形式的响应数据，一般 await 挂起操作，放在协程对象前面
                # file.close()
    print(video_name, '.mp4，下载成功！')


async def main():
    # 第一种写法
    # f1 = fun1()
    # await f1  # 一般 await 挂起操作，放在协程对象前面，
    tasks = []
    for video_dic in video_msg:
        tasks.append(asyncio.create_task(download_video(video_dic['name'], video_dic['url'])))

    await asyncio.wait(tasks)


if __name__ == '__main__':
    t1 = time.time()
    get_video_mag()

    # 下载视频
    asyncio.run(main())
    print('共耗时：', time.time() - t1)
